package com.tl.commonlibrary.ui;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import com.tl.commonlibrary.BuildConfig;
import com.tl.commonlibrary.R;
import com.tl.commonlibrary.tool.UIUtils;
import com.tl.commonlibrary.ui.widget.LoadingView;
import com.tl.commonlibrary.ui.widget.NetErrorView;
import com.tl.commonlibrary.ui.widget.NoDataView;
import com.tl.commonlibrary.ui.widget.ProgressDialog;
import com.tl.commonlibrary.ui.widget.TitleBar;

import java.lang.reflect.Field;

/**
 * Fragment基类
 * Created by jiangzhongshan on 15/7/10.
 */
public abstract class BaseFragment extends Fragment implements View.OnClickListener, NetErrorView.OnNetErrorClickListener, NoDataView.OnNoDataClickListener {
    protected String tag = null;
    protected View root;
    protected Context context;
    protected ProgressDialog dialog;
    private NetErrorView netErrorView;
    private LoadingView loadingView;
    protected NoDataView noDataView;
    private boolean fragmentViewCreated = false;//onCreateView方法是否已经执行
    private boolean isVisibleToUser = false;//当前fragment是否可见
    private boolean isUserVisibleHintInit = false;//懒加载是否加载完成
    private boolean calledSetUserVisibleHintMethod = false;//是否调用了setUserVisibleHint方法

    private TitleBar titleBar;
    /**
     * 和附属Actiity单向通信
     */
    private OnFragmentTriggerListener onFragmentTriggerdListener;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        init();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        init();
    }

    private void init() {
        this.context = getActivity();
        tag = this.getClass().getSimpleName();
        if (context instanceof OnFragmentTriggerListener) {
            setOnFragmentTriggerdListener((OnFragmentTriggerListener) context);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        if (BuildConfig.DEBUG) {
            System.out.println("Fragment" + "--onCreate " + this.toString());
        }
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        fragmentViewCreated = true;
        if (BuildConfig.DEBUG) {
            System.out.println("Fragment" + "--onCreateView " + this.toString());
        }
        if (isVisibleToUser || !calledSetUserVisibleHintMethod) {
            lazyLoad();
        }
        root.setClickable(true);
        return root;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        this.isVisibleToUser = isVisibleToUser;
        calledSetUserVisibleHintMethod = true;
        if (!isUserVisibleHintInit && fragmentViewCreated && isVisibleToUser) {
            lazyLoad();
        }
        super.setUserVisibleHint(isVisibleToUser);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        isUserVisibleHintInit = false;
    }

    /**
     * 懒加载方式下初始化数据：
     * 分两种情况：
     * 1：当setUserVisibleHint(isVisibleToUser)先执行且isVisibleToUser ==true 时，onCreateView()方法执行userVisibleHintInit（）
     * 2:onCreateView()先执行且执行,然后setUserVisibleHint(isVisibleToUser)isVisibleToUser ==true 时.setUserVisibleHint(isVisibleToUser)方法执行userVisibleHintInit（）
     */
    @CallSuper
    public void lazyLoad() {
        isUserVisibleHintInit = true;
    }

    public TitleBar getTitleBar() {
        if (titleBar == null) {
            titleBar = (TitleBar) root.findViewById(R.id.actionBar);
        }
        return titleBar;
    }

    /**
     * 使用之前xml中是否<include layout="@layout/action_bar" />
     *
     * @param resId
     */
    public void setTitle(int resId) {
        if (getTitleBar() != null) {
            titleBar.setTitle(resId);
        }
    }

    public void setTitleBackground(int resId) {
        if (getTitleBar() != null) {
            titleBar.setBackgroundResource(resId);
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        if (BuildConfig.DEBUG) {
            System.out.println("Fragment" + "--onActivityCreated " + this.toString());
        }
        super.onActivityCreated(savedInstanceState);
    }

    public void setOnFragmentTriggerdListener(OnFragmentTriggerListener onFragmentTriggerdListener) {
        this.onFragmentTriggerdListener = onFragmentTriggerdListener;
    }

    public void onFragmentTriggerd(int tag, Bundle bundle) {
        if (onFragmentTriggerdListener != null) {
            onFragmentTriggerdListener.onFragmentTrigger(tag, bundle);
        }
    }

    /**
     * fragment和Activity之间的通信
     */
    public interface OnFragmentTriggerListener {
        void onFragmentTrigger(int tag, Bundle bundle);
    }

    @Override
    public void onDestroy() {
        if (BuildConfig.DEBUG) {
            System.out.println("Fragment" + "--onDestroy " + this.toString());
        }
        super.onDestroy();
    }


    @Override
    public void onDetach() {
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class
                    .getDeclaredField("mChildFragmentManager");
            if (childFragmentManager != null) {
                childFragmentManager.setAccessible(true);
                childFragmentManager.set(this, null);
            }
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * activity在数据上需要的几种UI显示
     * 1.{@link ProgressDialog} Dialog方式，浮层之上，显示正在加载数据
     * 2.{@link LoadingView}view方式，与UI在同一层，显示正在加载数据
     * 3.{@link NetErrorView}view方式，与UI在同一层，加载失败无网络的情况需要用到
     * 4.{@link Toast} 浮层方式，显示其他消息提示
     */

    public void showProgressDialog() {
        showProgressDialog(true);
    }

    public void showProgressDialog(boolean cancelable) {
        dismissAll();
        if (dialog == null) {
            dialog = new ProgressDialog(context);

        }
        dialog.setCancelable(cancelable);
        dialog.show();
    }

    public void showProgressDialog(String message) {
        showProgressDialog(message, true);
    }

    public void showProgressDialog(String message, boolean cancelable) {
        dismissAll();
        if (dialog == null) {
            dialog = new ProgressDialog(context, message);
        } else {
            dialog.setMessage(message);
        }
        dialog.setCancelable(cancelable);
        dialog.show();
    }

    public void showProgressDialog(int messageResId) {
        showProgressDialog(messageResId, true);
    }

    public void showProgressDialog(int messageResId, boolean cancelable) {
        dismissAll();
        if (dialog == null) {
            dialog = new ProgressDialog(context, messageResId);
        } else {
            dialog.setMessage(messageResId);
        }
        dialog.setCancelable(cancelable);
        dialog.show();
    }

    public void dismissProgressDialog() {
        if (dialog != null) {
            dialog.dismiss();
        }
        dialog = null;
    }

    public void setProgressDialogMessage(String message) {
        if (dialog != null) {
            dialog.setMessage(message);
        }
    }

    public void setProgressDialogMessage(int messageResId) {
        if (dialog != null) {
            dialog.setMessage(messageResId);
        }
    }

    public void setCancelableProgressDailog(boolean flag) {
        if (dialog != null) {
            dialog.setCancelable(flag);
        }
    }

    public boolean isDialogShowing() {
        return dialog != null && dialog.isShowing();
    }


    public void showLoading() {
        showLoading("正在加载中...");
    }

    public void showLoading(int messageResId) {
        dismissAll();
        ViewGroup viewGroup = (ViewGroup) getView();
        if (viewGroup == null) {
            return;
        }
        if (loadingView == null) {
            loadingView = new LoadingView(context);
        }
        loadingView.setText(messageResId);
        if (loadingView.getParent() == null) {
            viewGroup.addView(loadingView);
        }
        loadingView.setVisibility(View.VISIBLE);
    }

    /**
     * 加载UI
     *
     * @param message
     */
    public void showLoading(String message) {
        dismissAll();
        ViewGroup viewGroup = (ViewGroup) getView();
        if (viewGroup == null) {
            return;
        }
        if (loadingView == null) {
            loadingView = new LoadingView(context);
        }
        loadingView.setText(message);
        if (loadingView.getParent() == null) {
            viewGroup.addView(loadingView);
        }
        loadingView.setVisibility(View.VISIBLE);
    }

    public void dismissLoading() {
        if (loadingView != null) {
            loadingView.setVisibility(View.GONE);
            if (loadingView.getParent() != null) {
                ViewGroup viewGroup = (ViewGroup) getView();
                if (viewGroup == null) {
                    return;
                }
                viewGroup.removeView(loadingView);
            }
        }
    }

    public boolean isLoadingShowing() {
        return loadingView != null && loadingView.getParent() != null && loadingView.getVisibility() == View.VISIBLE;
    }


    public void showNetError() {
        dismissAll();
        if (netErrorView == null) {
            netErrorView = new NetErrorView(context);
            netErrorView.setOnLoadFailedClickListener(this);
        }
        if (netErrorView.getParent() == null) {
            ViewGroup viewGroup = (ViewGroup) getView();
            if (viewGroup == null) {
                return;
            }
            viewGroup.addView(netErrorView);
        }
        netErrorView.setVisibility(View.VISIBLE);
    }

    public void dismissNetError() {
        if (netErrorView != null) {
            netErrorView.setVisibility(View.GONE);
            if (netErrorView.getParent() != null) {
                ViewGroup viewGroup = (ViewGroup) getView();
                if (viewGroup == null) {
                    return;
                }
                viewGroup.removeView(netErrorView);
            }
        }
    }

    public boolean isNerErrorShowing() {
        return netErrorView != null && netErrorView.getParent() != null && netErrorView.getVisibility() == View.VISIBLE;
    }

    public void showNoDataView() {
        dismissAll();
        if (noDataView == null) {
            noDataView = new NoDataView(context);
            noDataView.setNoDataClickListener(this);
        }
        if (noDataView.getParent() == null) {
            ViewGroup viewGroup = (ViewGroup) getView();
            if (viewGroup == null) {
                return;
            }
            viewGroup.addView(noDataView);
        }
        noDataView.setVisibility(View.VISIBLE);
    }

    /**
     *
     */
    public void dismissNoData() {
        if (noDataView != null) {
            noDataView.setVisibility(View.GONE);
            if (noDataView.getParent() != null) {
                ViewGroup viewGroup = (ViewGroup) getView();
                if (viewGroup == null) {
                    return;
                }
                viewGroup.removeView(noDataView);
            }
        }
    }

    public boolean isNoDataShowing() {
        return noDataView != null && noDataView.getParent() != null && noDataView.getVisibility() == View.VISIBLE;
    }

    /**
     * @param resId
     * @deprecated see {@link UIUtils#showToast(int)}
     */
    public void showToast(int resId) {
        showToast(resId, Toast.LENGTH_SHORT);
    }

    /**
     * @param
     * @deprecated see {@link UIUtils#showToast(String)}
     */
    public void showToast(String text) {
        showToast(text, Toast.LENGTH_SHORT);
    }

    /**
     * @param
     * @deprecated see {@link UIUtils#showToast(String, int)}
     */
    public void showToast(String text, int duration) {
        UIUtils.showToast(text, duration);
    }

    /**
     * @param resId
     * @deprecated see {@link UIUtils#showToast(int, int)}
     */
    public void showToast(int resId, int duration) {
        UIUtils.showToast(resId, duration);
    }

    /**
     * 加载成功之后，关闭所有不需要显示的UI
     */
    public void dismissAll() {
        dismissNetError();
        dismissLoading();
        dismissProgressDialog();
        dismissNoData();
    }

    /**
     * 重载该方法 实现 点击加载失败图标 的点击事件
     */
    @Override
    public void onNetErrorClicked() {
        dismissNetError();
    }

    @Override
    public void onNoDataClicked() {
    }

    public View getRoot() {
        return root;
    }

    /**
     * 隐藏键盘
     */
    public void hiddenKeyboard() {
        Activity activity = getActivity();
        if (activity != null) {
            if (activity.getWindow() != null && activity.getWindow().getCurrentFocus() != null) {
                ((InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE))
                        .hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(),
                                InputMethodManager.HIDE_NOT_ALWAYS);
            }
        }
    }

    private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";

    /**
     * 计算状态栏高度高度
     * getStatusBarHeight
     *
     * @return
     */
    public static int getStatusBarHeight() {
        return getInternalDimensionSize(Resources.getSystem(), STATUS_BAR_HEIGHT_RES_NAME);
    }

    private static int getInternalDimensionSize(Resources res, String key) {
        int result = 0;
        int resourceId = res.getIdentifier(key, "dimen", "android");
        if (resourceId > 0) {
            result = res.getDimensionPixelSize(resourceId);
        }
        return result;
    }
}
